using System;
using UnityEngine;

namespace Utils.Events
{
    public interface ISimpleEvent { }

    public class SimpleEvent : ISimpleEvent
    {
        private event Action _action;

        public IEventUnregister Register(Action action)
        {
            if (action == null)
                throw new ArgumentNullException(nameof(action));
            IEventUnregister eventUnregister = new GeneralEventUnregister(() => Unregister(action));
            _action += action;
            return eventUnregister;
        }

        public void Unregister(Action action)
        {
            if (action == null)
                return;
            _action -= action;
        }

        public void Invoke()
        {
            _action?.Invoke();
        }

        public void Clear()
        {
            _action = null;
        }

        public int Count => _action != null ? _action.GetInvocationList().Length : 0;
    }

    public class SimpleEvent<T> : ISimpleEvent
    {
        private event Action<T> _action;

        public IEventUnregister Register(Action<T> action)
        {
            if (action == null)
                throw new ArgumentNullException(nameof(action));
            IEventUnregister eventUnregister = new GeneralEventUnregister(() => Unregister(action));
            _action += action;
            return eventUnregister;
        }

        public void Unregister(Action<T> action)
        {
            if (action == null)
                return;
            _action -= action;
        }

        public void Invoke(T arg)
        {
            _action?.Invoke(arg);
        }

        public void Clear()
        {
            _action = null;
        }

        public int Count => _action != null ? _action.GetInvocationList().Length : 0;
    }

    public class SimpleEvent<T1, T2> : ISimpleEvent
    {
        private event Action<T1, T2> _action;

        public IEventUnregister Register(Action<T1, T2> action)
        {
            if (action == null)
                throw new ArgumentNullException(nameof(action));
            IEventUnregister eventUnregister = new GeneralEventUnregister(() => Unregister(action));
            _action += action;
            return eventUnregister;
        }

        public void Unregister(Action<T1, T2> action)
        {
            if (action == null)
                return;
            _action -= action;
        }

        public void Invoke(T1 arg1, T2 arg2)
        {
            _action?.Invoke(arg1, arg2);
        }

        public void Clear()
        {
            _action = null;
        }

        public int Count => _action != null ? _action.GetInvocationList().Length : 0;
    }

    public class GeneralEventUnregister : IEventUnregister
    {
        private Action _action;

        public GeneralEventUnregister(Action action)
        {
            _action = action;
        }

        public void Unregister()
        {
            Debug.Log("Unregister");
            _action?.Invoke();
        }
    }
}